# Responsability
# Contains the actual state of one monte carlo chain


ChainState <- setRefClass(    
  "chainstate"
  , fields = list(
    id="numeric", #Chain identification
    acceptedCount="numeric",  #Parameters accepted so far
    bestCount="numeric", #How many times does it change the best posterior
    bestPosterior="numeric", 
    lastPosterior="numeric", 
    lastParameters="data.frame",
    candidateParameters="data.frame",
    iteration="numeric",
    acceptanceRate="numeric",
    sumji="data.frame",
    sumjiSquared="data.frame"
  )
  , methods = list(
    initialize = function(..., acceptedCount=0, bestCount=0, iteration=1,lastParameters=data.frame(),
                          acceptanceRate=0.0, lastPosterior=0.0, bestPosterior=0.0, 
                          sumji=data.frame(), sumjiSquared=data.frame()) {
      callSuper(acceptedCount=acceptedCount, 
                bestCount=bestCount,
                iteration=iteration,
                acceptanceRate=acceptanceRate,
                lastPosterior=lastPosterior,
                bestPosterior=bestPosterior,
                lastParameters=lastParameters,
                sumji=sumji,
                sumjiSquared=sumjiSquared,
                ...)
    },
    #
    #
    # Check if the new posterior is accepted and update the state of the chain
    #
    #
    evaluateNewPosterior = function(newPosterior) {
      
      logdebug("METHOD IN: evaluateNewPosterior")

      logAlpha  <- (newPosterior) - (lastPosterior)
      
      #TODO understand this random here
      logRand   <- log(runif(1)) #Always under 0
      
      if (logAlpha >= logRand) {
        
        acceptedCount <<- acceptedCount + 1.0 
        lastParameters <<- candidateParameters
        lastPosterior <<- newPosterior

        if (newPosterior > bestPosterior) {
          
          bestPosterior <<-  newPosterior
          bestCount <<- bestCount + 1
          loginfo(paste("New best posterior for chain ", id, sep=""))
          loginfo(bestPosterior)
        }
      }
      
      acceptanceRate <<- acceptedCount / iteration
      
      logdebug("METHOD OUT: evaluateNewPosterior")
      
    }
    
  )#End methods List 
  
)#End RefClass


